﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace WowGuildSite.Armory
{
    public class ArmoryPrinter
    {
        private TextWriter  writer;
        private string      iconDirectory;
        private int         iconWidth;
        private int         iconHeight;

        public void PrintItem( ArmoryItem item )
        {
            writer.WriteLine("Item:         {0}",item.Id );
            WriteSeperator();
            writer.WriteLine("Name:         {0}",item.LocalizedName );
            writer.WriteLine("Type:         {0}",item.LocalizedType);
            writer.WriteLine("Slot:         {0}",item.Slot);
            writer.WriteLine("Quality:      {0}",item.Quality);
            writer.WriteLine("Armor:        {0}",item.Armor);
            writer.WriteLine("ItemLevel:    {0}",item.ItemLevel );
            writer.WriteLine("Level to use: {0}",item.RequiredLevel );
            writer.WriteLine("Durability:   {0}",item.Durability);
            writer.WriteLine("Bonding:      {0}",item.Bonding );

            PrintItemDamage(item.Damage);

            writer.WriteLine();
            PrintItemSockets(item.Sockets);

            string iconName = "ItemIcon" + item.Id.MainId.ToString();

            if ( item.Id.HasRandomProperties )
            {
                iconName = String.Format("ItemIcon{0}x{1}", item.Id.MainId, item.Id.RandomPropertiesId);    
            }
            WriteIcon( item.Icon,iconName );
        }

        public void PrintItemDamage( ArmoryItemDamage damage )
        {
            writer.WriteLine("Dps:          {0}",damage.Dps );
            writer.WriteLine("Damage min:   {0}",damage.Min );
            writer.WriteLine("Damage max:   {0}",damage.Max );
            writer.WriteLine("Speed:        {0}",damage.Speed );
        }

        public void PrintItemSockets( ArmoryItemSockets sockets )
        {
            writer.WriteLine("Item sockets:");
            WriteSeperator();

            foreach( ItemSocketType s in sockets.AvailableSockets )
            {
                writer.WriteLine("Socket:       {0}",s);
            }

            PrintItemEnchant(sockets.MatchEnchant);
        }

        public void PrintItemEnchant( ArmoryItemEnchant enchant )
        {
            writer.WriteLine("Match:        {0}",enchant.LocalizedText );
        }

        public void PrintGuild(ArmoryGuild guild)
        {
            writer.WriteLine("Guild: {0}", guild.Name);
            WriteSeperator();
            writer.WriteLine("Number of members: {0}", guild.Count);
            writer.WriteLine("Faction: {0}:{1}", guild.Faction, guild.LocalizedFaction);
            
            WriteIcon(guild.FactionIcon, guild.Name + "GuildFactionIcon" );
            
            writer.WriteLine();
            writer.WriteLine("Guild members:");

            // Print out the guild members:
            foreach (ArmoryCharacter c in guild)
            {
                WriteSeperator();
                PrintCharacter(c);
                writer.WriteLine();
            }
        }

        public void PrintCharacter(ArmoryCharacter character)
        {
            writer.WriteLine("Character: {0}", character.Name);
            WriteSeperator();
            writer.WriteLine("Level:    {0}",character.Level );
            writer.WriteLine("Class:    {0}:{1}", character.Class, character.LocalizedClass);
            writer.WriteLine("Race:     {0}:{1}", character.Race, character.LocalizedRace);
            writer.WriteLine("Gender:   {0}:{1}", character.Gender, character.LocalizedGender);
            writer.WriteLine("Faction:  {0}:{1}", character.Faction,character.LocalizedFaction);
            writer.WriteLine("Talents:  {0}/{1}/{2}", character.TalentTreePoints[0], character.TalentTreePoints[1], character.TalentTreePoints[2]);

            WriteBar(character.HealthBar);
            WriteBar(character.SecondaryBar);

            if (character.Guild != null)
            {
                writer.WriteLine("Guild: {0}", character.Guild.Name);
                writer.WriteLine("Guild rank: {0}:{1}", character.GuildRank,character.LocalizedGuildRank);
            }
            else
            {
                writer.WriteLine("Guild: Not in a guild");
            }

            WriteIcon(character.FactionIcon, character.Name + "CharacterFactionIcon");
            WriteIcon(character.GenderIcon, character.Name + "CharacterGenderIcon");
            WriteIcon(character.ClassIcon, character.Name + "CharacterClassIcon");
            WriteIcon(character.RaceIcon, character.Name + "CharacterRaceIcon");

            writer.WriteLine();
            writer.WriteLine("Base stats:");
            WriteSeperator();
            WriteBaseStats( character.BaseStats );

            writer.WriteLine();
            writer.WriteLine("Defense stats:");
            WriteSeperator();
            WriteDefenseStats(character.DefenseStats);

            writer.WriteLine();
            writer.WriteLine("Melee combat stats:");
            WriteSeperator();
            WriteMeleeStats(character.MeleeStats);

            writer.WriteLine();
            writer.WriteLine("Ranged combat stats:");
            WriteSeperator();
            WriteRangedStats(character.RangedStats);

            writer.WriteLine();
            writer.WriteLine("Spell stats:");
            WriteSeperator();
            WriteSpellStats(character.SpellStats);

            writer.WriteLine();
            writer.WriteLine("Resistance stats:");
            WriteSeperator();
            WriteResistanceStats(character.ResistanceStats);

            writer.WriteLine();
            writer.WriteLine("Reputation:");
            WriteSeperator();
            WriteReputations(character.Reputation);

            writer.WriteLine();
            writer.WriteLine("Skills:");
            WriteSeperator();
            WriteSkills(character.Skills);
        }

        public void WriteBar(ArmoryBar bar)
        {
            writer.WriteLine("{0}: {1}", bar.Type, bar.Effective);
        }

        public void WriteReputations(ArmoryReputationCollection reputations)
        {
            foreach (ArmoryReputation r in reputations)
            {
                writer.WriteLine("Category: {0}:{1}, Name: {2}:{3}, Points: {4}, Status: {5}", r.Category, r.LocalizedCategory, r.Key, r.LocalizedName, r.Value, r.Status);
            }
        }

        public void WriteSkills(ArmorySkillCollection skills)
        {
            foreach (ArmorySkill s in skills)
            {
                writer.WriteLine("Category: {0}:{1}, Name: {2}:{3}, Value: {4}, Max: {5}", s.Category, s.LocalizedCategory, s.Key, s.LocalizedName, s.Current, s.Max);
            }
        }

        public void WriteBaseStats(ArmoryBaseStatCollection baseStats)
        {
            foreach (ArmoryBaseStat s in baseStats)
            {
                writer.WriteLine("{0}: {1}-{2}", s.Type, s.Base, s.Effective);
            }
        }

        public void WriteMeleeStats(ArmoryMeleeStats meleeStats )
        {
            WriteCombatStat(meleeStats.MainHand);
            WriteCombatStat(meleeStats.OffHand);

            writer.WriteLine("Crit chance: {0} %", meleeStats.CritChance);
            writer.WriteLine("Power: {0}-{1}", meleeStats.PowerBase, meleeStats.PowerEffective);
            writer.WriteLine("Hit Rating: {0}", meleeStats.HitRating);
        }

        public void WriteResistanceStats(ArmoryResistanceStats resistanceStats)
        {
            writer.WriteLine("Fire:     {0}", resistanceStats.FireResistance);
            writer.WriteLine("Frost:    {0}", resistanceStats.FrostResistance);
            writer.WriteLine("Arcane:   {0}", resistanceStats.ArcaneResistance);
            writer.WriteLine("Shadow:   {0}", resistanceStats.ShadowResistance);
            writer.WriteLine("Nature:   {0}", resistanceStats.NatureResistance);
            writer.WriteLine("Holy      {0}", resistanceStats.HolyResistance);
        }

        public void WriteSpellStats(ArmorySpellStats spellStats)
        {
            writer.WriteLine("Bonus healing: {0}", spellStats.BonusHealing);
            writer.WriteLine("Hit rating: {0}", spellStats.HitRating);
            writer.WriteLine("Mana regeneration: {0}, {1} while casting", spellStats.ManaRegen, spellStats.ManaRegenCasting);
            writer.WriteLine("Penetration: {0}", spellStats.Penetration);
            writer.WriteLine("Magic bonuses:");

            Array magicTypes = Enum.GetValues(typeof(MagicType));
            foreach (MagicType t in magicTypes)
            {
                writer.WriteLine("{0}: {1} (+ dmg) {2} % (crit chance)", t, spellStats.GetBonusDamage(t), spellStats.GetCritChance(t));
            }

        }

        public void WriteRangedStats(ArmoryRangedStats rangedStats)
        {
            WriteCombatStat(rangedStats.Ranged);
            writer.WriteLine("Crit chance: {0} %", rangedStats.CritChance);
            writer.WriteLine("Power: {0}-{1}", rangedStats.PowerBase, rangedStats.PowerEffective);
            writer.WriteLine("Hit Rating: {0}", rangedStats.HitRating);
        }

        public void WriteDefenseStats(ArmoryDefenseStats defenseStats)
        {
            writer.WriteLine("Armor:        {0}-{1}, Absorption: {2} %", defenseStats.ArmorBase, defenseStats.ArmorEffective, defenseStats.ArmorAbsorption);
            writer.WriteLine("Defense:      {0}", defenseStats.Defense);
            writer.WriteLine("Resilience:   {0} Damage: {1} % Hit: {2} %", defenseStats.Resilience, defenseStats.ResilienceDamage, defenseStats.ResilienceHit);
            writer.WriteLine("Block:        {0} %", defenseStats.Block);
            writer.WriteLine("Dodge:        {0} %", defenseStats.Dodge);
            writer.WriteLine("Parry:        {0} %", defenseStats.Parry);
        }

        public void WriteCombatStat(ArmoryCombatStat combatStat)
        {
            writer.WriteLine("{0}: Damage: {1}-{2} Dps: {3} Speed: {4} Skill: {5}", combatStat.Type, combatStat.MinDamage, combatStat.MaxDamage, combatStat.Dps, combatStat.Speed, combatStat.Skill);
        }

        public void WriteIcon(ArmoryIcon icon, string name)
        {
            if (icon == null)
            {
                return;
            }

            if (!string.IsNullOrEmpty(iconDirectory))
            {
                if (!Directory.Exists(iconDirectory))
                {
                    Directory.CreateDirectory(iconDirectory);
                }

                string filename = Path.Combine(iconDirectory, name + ".png");
                Bitmap data     = icon.GetIconData(iconWidth, iconHeight);

                if (data != null)
                {
                    data.Save(filename, ImageFormat.Png);
                }
            }
        }

        private void WriteSeperator()
        {
            writer.WriteLine("===================================================");
        }

        public ArmoryPrinter(TextWriter writer,string iconDirectory,int iconWidth,int iconHeight )
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            if (iconWidth < 2)
            {
                throw new ArgumentException("Icon width is to small", "iconWidth");
            }
            if (iconHeight < 2)
            {
                throw new ArgumentException("Icon height is to small", "iconHeight");
            }
            
            this.iconDirectory  = iconDirectory;
            this.iconWidth      = iconWidth;
            this.iconHeight     = iconHeight;
            this.writer         = writer;
        }
    }
}
